Conversation
6b7b6ae to
dea7127
Compare
|
The origin idea of Nano Stores is to move logic from React components. In general, I see the nanostores’s way to solve this task in: import { listenKeys } from 'nanostores'
function bindAnotherAction () {
const unbind = listenKeys(myStore, ['field'], value => {
if (value.field === 'satisfies-some-condition') {
triggerAnotherAction()
}
})
return unbind
}
function MyComponent() {
useEffect(bindAnotherAction)
}Do you have reasons to do have this logic in React component? |
|
I think this is more of a idealistic vs pragmatic approach I.e. in a perfect world it might be a good practice to make sure that no local component logic interferes with logic that is handled by the stores (outside react) In practice, we just wanna be able to do stuff and have the tools that help us. Extracting |
|
OK, let’s add tests and docs. I agree that sometimes people may want old approach. |
dea7127 to
16ffa43
Compare
|
Hi again! I'm not sure whether the If everything's fine the next thing to do is to update the docs |
|
|
||
| type Listener<SomeStore extends Store> = ( | ||
| value: StoreValue<SomeStore>, | ||
| changed?: SomeStore extends MapStore ? StoreValue<SomeStore> : never |
There was a problem hiding this comment.
Does this parameter only have a value if the store is map store?
And what is its value if the store value is a primitive?
There was a problem hiding this comment.
Does this parameter only have a value if the store is map store?
Yeap
And what is its value if the store value is a primitive?
In this case you do not have store.setKey and we have no easy way to detect changes
There was a problem hiding this comment.
Well I was asking because of this: https://github.com/nanostores/react/pull/2/files#r744618456
index.js
Outdated
| React.useEffect(() => { | ||
| let listener = (value, changed) => listenerRef.current(value, changed) | ||
| if (opts.leading) { | ||
| listener(store.get(), null) |
There was a problem hiding this comment.
Is it correct to pass null here?
There was a problem hiding this comment.
I think it is better to call listener(store.get())
16ffa43 to
a37b553
Compare
|
LGTM. Do you want to add anything else? |
|
Great, thanks! |
|
Let’s update docs in this PR |
| return store.get() | ||
| } | ||
|
|
||
| export function useStoreListener(store, opts = {}) { |
There was a problem hiding this comment.
it is worth moving the new hook into a separate file: this way it will not affect those who do not need it.
| } | ||
| }, [store, '' + opts.keys, opts.leading]) | ||
|
|
||
| return null |
There was a problem hiding this comment.
the return does nothing, it seems it can be removed.
Motivation:
A common pattern is to react to some store change in an effect:
While this does the job, unfortunately it makes the whole component re-render when store changes, even if the
fielddoesn't yet satisfy our condition.Solution here would be to create a hook that is designed to only trigger effects and not interfere with the render phase:
That way, we can use the familiar effect pattern, but avoid unwanted re-renders and calls of other hooks in the component
If you decide this is a good feature, I'll finish the pull request by updating types, tests and docs, thanks!